/*
* Copyright (c) 2021 Talkweb Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/*
* subdev 测试程序
*/

#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <pthread.h>

#include "tiot_state_api.h"
#include "tiot_sysdep_api.h"
#include "tiot_mqtt_api.h"
#include "cJSON.h"

#include"tiot_mqtt.h"

#include"tiot_subdev_api.h"

tiot_subdev_dev_t g_subdev[] = {
    {
        "g0K7gI7vI",
        "p07rgLryL"
    }
};

extern tiot_sysdep_portfile_t g_tiot_sysdep_portfile;

static pthread_t g_mqtt_process_thread;
static pthread_t g_mqtt_recv_thread;
static uint8_t flag_mqtt_process_thread_running = 0;
static uint8_t flag_mqtt_recv_thread_running = 0;

int32_t test_print_logcb(int32_t code, char *message)
{
    printf("%s", message);
    return 0;
}

void test_mqtt_event_ctx(void *ctx, const tiot_mqtt_event_t *event, void *userdata)
{
   if(event->type==TIOT_MQTT_EVENT_CONNECT) {
        printf("TIOT_MQTTEVT_CONNECT\n");
    }
    else if(event->type==TIOT_MQTT_EVENT_RECONNECT) {
        printf("tiot_MQTTEVT_RECONNECT\n");
    }
    else if(event->type==TIOT_MQTT_EVENT_DISCONNECT) {
        char *cause;
        if(event->data.disconnect == TIOT_MQTTDISCONNEVT_NETWORK_DISCONNECT) {
            cause="network disconnect";
        }
        else {
            "heartbeat disconnect";
        }
        printf("tiot_MQTTEVT_DISCONNECT: %s\n", cause);
    }
}

void test_mqtt_default_recv_ctx(void *ctx, const tiot_mqtt_recv_t *packet, void *userdata)
{
    if (packet->type == TIOT_MQTTRECV_HEARTBEAT_RESPONSE) {
        printf("heartbeat response\n");
    }
    else if(packet->type==TIOT_MQTTRECV_PUB){
        int res = 0;
            char *data = NULL;
            printf("pub, qos: %d, topic: %.*s\n", packet->data.pub.qos, packet->data.pub.topic_len, packet->data.pub.topic);
            printf("pub, payload: %.*s\n", packet->data.pub.payload_len, packet->data.pub.payload);
            tiot_mqtt_sub_recv_data(ctx, packet->data.pub.payload, &data);
            if (res >= 0) {
                printf("tiot_mqtt_sub successed\n");
            }
            else {
                printf("tiot_mqtt_sub failed, res: -0x%04X\n", -res);
                return;
            }
            printf("data:%s\n",data); 
            g_tiot_sysdep_portfile.service_sysdep_free(data); //注意需要释放 
    }
}

void *test_mqtt_process_thread(void *ctx)
{
    int32_t res = RET_SUCCESS;

    while (1)
    {
        sleep(1);
        res = tiot_mqtt_process(ctx);
        if (res != RET_USER_INPUT_EXEC_DISABLED) {}
        else {
            break;
        }
    }

    return NULL;
}

void *test_mqtt_recv_thread(void *ctx)
{
    int32_t res = RET_SUCCESS;

    while (1)
    {
         res = tiot_mqtt_recv(ctx);
        if(!flag_mqtt_recv_thread_running) {
            break;
        }
        if (res < RET_SUCCESS && res==RET_USER_INPUT_EXEC_DISABLED ) {
            break;
        }
        else {
            sleep(2);
        }
        
    }
    
    return NULL;
}

int main(int argc, char *argv[])
{
    int32_t res = RET_SUCCESS;
    void *mq_process = NULL;
    int8_t public_instance = 0;
    // char *url = "192.168.146.19";
    // char *url = "116.63.137.223";
    // char *url = "192.168.141.77";
    char *url = "116.63.137.223";
    char host[100] = {0};
    uint16_t port = 1883;//5682,1883

    char *product_key = "r0SPgcPsc";
    char *device_name = "r0plgRlvR";
    char *device_secret = "a57cdfc800205846";

    tiot_set_print_callback(test_print_logcb);
    tiot_sysdep_set_portfile(&g_tiot_sysdep_portfile);

    mq_process = tiot_mqtt_init();
    if (mq_process == NULL)
    {
        printf("tiot_mqtt_init failed\n");
        return -1;
    }

    if (1 == public_instance)
    {
        snprintf(host, 100, "%s.%s", product_key, url);
    }
    else
    {
        snprintf(host, 100, "%s", url);
    }

    tiot_mqtt_set_host(mq_process,host);
    tiot_mqtt_set_port(mq_process,&port);
    tiot_mqtt_set_product_key(mq_process,product_key);
    tiot_mqtt_set_device_name(mq_process,device_name);
    tiot_mqtt_set_device_secret(mq_process,device_secret);
    tiot_mqtt_recv_ctx(mq_process,test_mqtt_default_recv_ctx);
    tiot_mqtt_event_ctx(mq_process,test_mqtt_event_ctx);

    res = tiot_mqtt_connect(mq_process);
    if (res >= RET_SUCCESS)
    {
        printf("tiot_mqtt_connect successed\n");
    }
    else {
        tiot_mqtt_deinit(&mq_process);
        printf("tiot_mqtt_connect failed: -0x%04X\n", -res);
        return -1;
    }


     /* mqtt订阅MQTT动态注册响应消息 */
    {
        char *sub_topic = "persistent://T0001/default/r0SPgcPsc.r0plgRlvR.sys.sub.register_reply";

        res = tiot_mqtt_sub(mq_process, sub_topic, NULL, 1, NULL);
        if (res >= 0)
        {
            printf("tiot_mqtt_sub successed");
        }
        else {
            printf("tiot_mqtt_sub failed, res: -0x%04X\n", -res);
            return -1;
        }
    }

    /* mqtt发布MQTT动态注册消息 */
    {
        char *pub_topic = "persistent://T0001/default/r0SPgcPsc.r0plgRlvR.sys.sub.register";
        char *pub_payload = "{\"deviceName\":\"e0Nygbyxb\",\"productKey\":\"g0K7gI7vI\"}";
        res = tiot_mqtt_pub_with_method(mq_process, pub_topic, (uint8_t *)pub_payload, (uint32_t)strlen(pub_payload), 0, "sub.register");
        if (res >= 0)
        {
            printf("tiot_mqtt_sub successed\n");
        }
        else {
            printf("tiot_mqtt_sub failed, res: -0x%04X\n", -res);
            return -1;
        }
    }

    

#if 0
    /* 子设备退网响应 */
    {
        char *sub_topic = "persistent://T0001/default/r0SPgcPsc.r0plgRlvR.sys.topo.delete_reply";

        res = tiot_mqtt_sub(mq_process, sub_topic, NULL, 1, NULL);
        if (res >= 0)
        {
            printf("tiot_mqtt_sub successed\n");
        }
        else {
            printf("tiot_mqtt_sub failed, res: -0x%04X\n", -res);
            return -1;
        }
    }

    /* 子设备退网 */
    {
        char *pub_topic = "persistent://T0001/default/r0SPgcPsc.r0plgRlvR.sys.topo.delete";
        uint8_t sign[32]={0};
        printf("sign is :%s\n",sign);
        core_hmac_sha256((const uint8_t*)device_name,(uint32_t)strlen(device_name),(const uint8_t*)device_secret,(uint32_t)strlen(device_secret),sign);
        char sign_str[32];
        core_hex2str(sign,32,sign_str,0);

        printf("sign is :%s\n",sign_str);
        char *pub_payload=NULL;

        cJSON *data=cJSON_CreateArray();
        size_t i;
        for (i = 0; i < sizeof(g_subdev)/sizeof(tiot_subdev_dev_t); i++)
        {
            cJSON *item=cJSON_CreateObject();
            cJSON *product_key_json=cJSON_CreateString(g_subdev[i].product_key);
            cJSON_AddItemToObject(item,"productKey",product_key_json);

            cJSON *device_name_json=cJSON_CreateString(g_subdev[i].device_name);
            cJSON_AddItemToObject(item,"deviceName",device_name_json);

            cJSON_AddItemToArray(data,item);
        }
        pub_payload=cJSON_PrintUnformatted(data);

        res = tiot_mqtt_pub_with_method(mq_process, pub_topic, (uint8_t *)pub_payload, (uint32_t)strlen(pub_payload), 0, "topo.delete");
        if (res >= 0)
        {
            printf("tiot_mqtt_pub successed\n");
        }
        else {
            printf("tiot_mqtt_pub failed, res: -0x%04X\n", -res);
            return -1;
        }
    }
#endif


#if 0
     /* 子设备上线 */
    {
        char *pub_topic = "persistent://T0001/default/r0SPgcPsc.r0plgRlvR.sys.sub.login";
        uint8_t sign[32]={0};
        printf("sign is :%s\n",sign);
        core_hmac_sha256((const uint8_t*)device_name,(uint32_t)strlen(device_name),(const uint8_t*)device_secret,(uint32_t)strlen(device_secret),sign);
        char sign_str[32];
        core_hex2str(sign,32,sign_str,0);

        printf("sign is :%s\n",sign_str);
        char *pub_payload=NULL;

        cJSON *data=cJSON_CreateArray();
        size_t i;
        for (i = 0; i < sizeof(g_subdev)/sizeof(tiot_subdev_dev_t); i++)
        {
            cJSON *item=cJSON_CreateObject();
            cJSON *product_key_json=cJSON_CreateString(g_subdev[i].product_key);
            cJSON_AddItemToObject(item,"productKey",product_key_json);

            cJSON *device_name_json=cJSON_CreateString(g_subdev[i].device_name);
            cJSON_AddItemToObject(item,"deviceName",device_name_json);

            cJSON *sign_json=cJSON_CreateString(sign_str);
            cJSON_AddItemToObject(item,"sign",sign_json);

            cJSON *signmethod_json=cJSON_CreateString("hmacsha256");
            cJSON_AddItemToObject(item,"signmethod",signmethod_json);

            char temp_time[13]={0};
            uint8_t len=0;
            core_uint642str(service_log_get_timestamp(((service_mq_process_t *)mq_process)->sysdep),temp_time,&len);
            temp_time[13]='\0';
            cJSON *time_json=cJSON_CreateString(temp_time);
            cJSON_AddItemToObject(item,"timestamp",time_json);

            cJSON_AddItemToArray(data,item);
        }
        pub_payload=cJSON_PrintUnformatted(data);

        res = tiot_mqtt_pub_with_method(mq_process, pub_topic, (uint8_t *)pub_payload, (uint32_t)strlen(pub_payload), 0, "sub.login");
        if (res >= 0)
        {
            printf("tiot_mqtt_pub successed\n");
        }
        else {
            printf("tiot_mqtt_pub failed, res: -0x%04X\n", -res);
            return -1;
        }
    }
#endif

#if 0
     /* 子设备下线 */
    {
        char *pub_topic = "persistent://T0001/default/r0SPgcPsc.r0plgRlvR.sys.sub.logout";
        uint8_t sign[32]={0};
        printf("sign is :%s\n",sign);
        core_hmac_sha256((const uint8_t*)device_name,(uint32_t)strlen(device_name),(const uint8_t*)device_secret,(uint32_t)strlen(device_secret),sign);
        char sign_str[32];
        core_hex2str(sign,32,sign_str,0);

        printf("sign is :%s\n",sign_str);
        char *pub_payload=NULL;

        cJSON *data=cJSON_CreateArray();
        size_t i;
        for (i = 0; i < sizeof(g_subdev)/sizeof(tiot_subdev_dev_t); i++)
        {
            cJSON *item=cJSON_CreateObject();
            cJSON *product_key_json=cJSON_CreateString(g_subdev[i].product_key);
            cJSON_AddItemToObject(item,"productKey",product_key_json);

            cJSON *device_name_json=cJSON_CreateString(g_subdev[i].device_name);
            cJSON_AddItemToObject(item,"deviceName",device_name_json);

            cJSON_AddItemToArray(data,item);
        }
        pub_payload=cJSON_PrintUnformatted(data);

        res = tiot_mqtt_pub_with_method(mq_process, pub_topic, (uint8_t *)pub_payload, (uint32_t)strlen(pub_payload), 0, "sub.logout");
        if (res >= 0)
        {
            printf("tiot_mqtt_pub successed\n");
        }
        else {
            printf("tiot_mqtt_pub failed, res: -0x%04X\n", -res);
            return -1;
        }
    }
#endif


    flag_mqtt_process_thread_running = 1;
    res = g_tiot_sysdep_portfile.service_task_create(&g_mqtt_process_thread, NULL, test_mqtt_process_thread, mq_process);
    if (res >= 0)
    {
        printf("pthread_create test_mqtt_process_thread successed\n");
    }
    else {
        printf("pthread_create test_mqtt_process_thread failed: %d\n", res);
        return -1;
    }

    flag_mqtt_recv_thread_running = 1;
    res = g_tiot_sysdep_portfile.service_task_create(&g_mqtt_recv_thread, NULL, test_mqtt_recv_thread, mq_process);
    if (res >= 0)
    {
        printf("pthread_create test_mqtt_recv_thread successed\n");
    }
    else {
        printf("pthread_create test_mqtt_recv_thread failed: %d\n", res);
        return -1;
    }

    while (1)
    {
        sleep(1);
    }

    flag_mqtt_process_thread_running = 0;
    flag_mqtt_recv_thread_running = 0;
    sleep(1);
    res = tiot_mqtt_disconnect(mq_process);
    if (res >= RET_SUCCESS)
    {
        printf("tiot_mqtt_disconnect successed\n");
    }
    else {
        tiot_mqtt_deinit(&mq_process);
        printf("tiot_mqtt_disconnect failed: -0x%04X\n", -res);
        return -1;
    }

    res = tiot_mqtt_deinit(&mq_process);
    if (res >= RET_SUCCESS)
    {
        printf("tiot_mqtt_deinit successed\n");
    }
    else {
        printf("tiot_mqtt_deinit failed: -0x%04X\n", -res);
        return -1;
    }

    g_tiot_sysdep_portfile.service_task_join(&g_mqtt_process_thread, NULL);
    g_tiot_sysdep_portfile.service_task_join(&g_mqtt_recv_thread, NULL);

    return 0;
}
